package com.sencorsta.ids;

import com.alibaba.fastjson.JSONObject;
import com.sencorsta.ids.core.configure.GlobalConfigure;
import com.sencorsta.ids.core.configure.SysConfig;
import com.sencorsta.ids.core.configure.TypeProtocol;
import com.sencorsta.ids.core.configure.TypeSerialize;
import com.sencorsta.ids.core.function.FunctionSystem;
import com.sencorsta.ids.core.log.Out;
import com.sencorsta.ids.core.tcp.opensocket.OpenDecoder;
import com.sencorsta.ids.core.tcp.opensocket.OpenEncoder;
import com.sencorsta.ids.core.tcp.opensocket.OpenMessage;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.concurrent.DefaultThreadFactory;
import io.netty.util.concurrent.ThreadPerTaskExecutor;

import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;

public class OpenSocketClient {



    private String serverIp="192.168.0.89";
    private int serverPort=10101;
    private Bootstrap bootstrap;
    private EventLoopGroup group;

    private static final EventLoopGroup m_loop =new NioEventLoopGroup(0,new ThreadPerTaskExecutor(new DefaultThreadFactory("Client")));

    public OpenSocketClient(ChannelInitializer<SocketChannel> factory) {
        this(factory, m_loop);
    }

    protected OpenSocketClient(ChannelInitializer<SocketChannel> factory, EventLoopGroup loop) {
        group = new NioEventLoopGroup();
        bootstrap = new Bootstrap();
        bootstrap.channel(NioSocketChannel.class);
        bootstrap.option(ChannelOption.TCP_NODELAY, true);
        bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
        bootstrap.handler(factory);
        bootstrap.group(loop);

        // channelFuture = bootstrap.connect(serverIp, serverPort).sync();
    }

    public Channel connect(String host, int port) {
        try {
            this.serverIp = host;
            this.serverPort = port;
            ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
            future.awaitUninterruptibly(10, TimeUnit.SECONDS);
            if (!future.isSuccess()) {
                if (future.cause() != null) {
                    Out.trace("连接服务器出错:",future.cause().getMessage());
                }
                return null;
            }
            return future.channel();
        } catch (Exception e) {
            Out.error("连接服务器出错", "host:", host, " port:", port + " -> " + e.getMessage());
            //e.printStackTrace();
            return null;
        }
    }


    public void close(Channel channel) throws InterruptedException {
        Out.trace("开始关闭链接");
        channel.closeFuture().sync();
        group.shutdownGracefully();
        Out.trace("关闭链接");
    }


    public static void main(String[] args) throws InterruptedException {
        SysConfig.getInstance();

        OpenSocketClient openSocketClient=new OpenSocketClient(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                ChannelPipeline pipeline = ch.pipeline();
                pipeline.addLast("decoder", new OpenDecoder());
                pipeline.addLast("encoder", new OpenEncoder());
                pipeline.addLast("handler", new OpenSocketClientHandler());
            }
        });

        Channel channel=openSocketClient.connect("192.168.0.89",10101);


        while (!channel.isActive()){

        }
        {
            OpenMessage om = new OpenMessage();
            om.method = "proxy.ConnectByJson";

            JSONObject json = new JSONObject();

            json.put("123123", "123123");

            om.data = json.toJSONString().getBytes(GlobalConfigure.UTF_8);
            om.serializeType = TypeSerialize.TYPE_JSON;
            om.header.type = TypeProtocol.TYPE_REQ;
            channel.writeAndFlush(om);
        }


        FunctionSystem.addScheduleJob(()->{
            OpenMessage om=new OpenMessage();
            om.method="AppTemp.testApp";

            JSONObject json=new JSONObject();

            json.put("123123","123123");

            om.data=json.toJSONString().getBytes(GlobalConfigure.UTF_8);
            om.serializeType= TypeSerialize.TYPE_JSON;
            om.header.type= TypeProtocol.TYPE_REQ;
            channel.writeAndFlush(om);
        },1,1, TimeUnit.SECONDS);

    }

}
